package gui;

import data.Player;
import data.Position;
import data.selection.SelectionObject;
import engine.Pitch;
import gui.PitchGUI.ButtonHandler;
import gui.customControl.PitchCell;
import gui.util.IconFactory;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.swing.JPanel;

public class PitchBoardGUI extends JPanel {
	/**
	 * Instance.
	 */
	private static PitchBoardGUI instance;

	private static final long serialVersionUID = -8157441137529061935L;

	/**
	 * Getter for the "instance" property.
	 * 
	 * @return the instance
	 * 
	 * @author Tomasz Dąbrowski
	 */
	public static PitchBoardGUI getInstance() {
		return instance;
	}

	ButtonHandler m_buttonHandler;

	PitchCell m_buttons[][];

	public PitchBoardGUI(final Dimension appDimension, final ButtonHandler handler) {
		PitchBoardGUI.instance = this;
		this.setPreferredSize(new Dimension(appDimension.width - 100, appDimension.height - 200));
		m_buttons = new PitchCell[Pitch.PITCH_WIDTH][Pitch.PITCH_HEIGHT];
		m_buttonHandler = handler;
	}

	public void highlightCells(final Map<Color, Collection<Position>> positions, final boolean path) {
		for (Entry<Color, Collection<Position>> e : positions.entrySet()) {
			for (Position p : e.getValue()) {
				PitchCell cell = m_buttons[p.x()][p.y()];
				if (path) {
					cell.setPathHighlight(e.getKey());
				} else {
					cell.setHighlight(e.getKey());
				}
			}
		}
	}

	public void clearHighlightCells() {
		for (int x = 0; x < m_buttons.length; x++) {
			for (int y = 0; y < m_buttons[x].length; y++) {
				m_buttons[x][y].setPathHighlight(null);
				m_buttons[x][y].setHighlight(null);
			}
		}
	}

	public void refreshCells() {
		for (int x = 0; x < m_buttons.length; x++) {
			for (int y = 0; y < m_buttons[x].length; y++) {
				m_buttons[x][y].update();
			}
		}
	}

	/**
	 * Removes all selection object highlight objects and updates all selected
	 * cells.
	 */
	public void clearSelectionHighlight() {
		final List<SelectionObject> selObjs = IconFactory.instance().getSelection();
		// Keep a copy of the array.
		final ArrayList<SelectionObject> tempList = new ArrayList<SelectionObject>(selObjs);

		// Clear the selection -- this empties the selObjs array so that's why
		// we need a copy
		IconFactory.instance().clearSelection();

		for (final SelectionObject sel : tempList) {
			updateSelectedCells(sel);
		}
	}

	public void launchGame() {
		this.setLayout(new GridLayout(Pitch.PITCH_HEIGHT, Pitch.PITCH_WIDTH, 0, 0));

		// Initialise buttons
		for (int i = 0, count = 0; i < Pitch.PITCH_WIDTH; i++) {
			m_buttons[i] = new PitchCell[Pitch.PITCH_HEIGHT];
			for (int j = 0; j < Pitch.PITCH_HEIGHT; j++, count++) {
				m_buttons[i][j] = new PitchCell(i, j);

				// add listeners to the buttons
				m_buttons[i][j].addActionListener(m_buttonHandler);
			}
		}

		// Put button in the GUI in the right order!
		for (int j = 0; j < Pitch.PITCH_HEIGHT; j++) {
			for (int i = 0; i < Pitch.PITCH_WIDTH; i++) {
				this.add(m_buttons[i][j]);
			}
		}
	}

	/**
	 * Removes a specific selection highlight object and updates the
	 * corresponding cells.
	 * 
	 * @param selObj
	 *            The selection object to remove
	 */
	public void removeSelectionHighlight(final SelectionObject selObj) {
		IconFactory.instance().removeSelection(selObj);
		updateSelectedCells(selObj);
	}

	/**
	 * Resets the buttons to the default state.
	 */
	public void resetButton(final int x, final int y) {
		m_buttons[x][y].setData(null, false);
	}

	/**
	 * Sets the buttons of the grid with the relevant data.
	 * 
	 * @param x
	 *            ,y - Position of cells on board
	 * @param player
	 *            - a local reference to a player object
	 * @param isBall
	 *            - signals if the location contains only the ball
	 */
	public void setButtonData(final int x, final int y, final Player player, final boolean isBall) {
		m_buttons[x][y].setData(player, isBall);
	}

	/**
	 * Associates a selection highlight object to the pitch GUI
	 * 
	 * @param selObj
	 *            the selection object. Use a null object to reset!
	 */
	public void setSelectionHighlight(final SelectionObject selObj) {
		IconFactory.instance().addSelection(selObj);
		updateSelectedCells(selObj);
	}

	/**
	 * Updates the cells specified by the given selection object
	 * 
	 * @param selObj
	 *            Selection object performing the isSelected check
	 */
	private void updateSelectedCells(final SelectionObject selObj) {
		for (int i = 0; i < m_buttons.length; i++) {
			for (int j = 0; j < m_buttons[i].length; j++) {
				if (selObj.isSelected(new Position(i, j))) {
					m_buttons[i][j].updateHighlight();
				}
			}
		}
	}
}
